package com.aibaixun.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.aibaixun.common.core.domain.R;
import com.aibaixun.common.core.service.ConfigService;
import com.aibaixun.common.exception.ServiceException;
import com.aibaixun.common.utils.BeanCopyUtils;
import com.aibaixun.common.utils.StringUtils;
import com.aibaixun.system.domain.DicmAddress;
import com.aibaixun.system.domain.DicmCabinet;
import com.aibaixun.system.domain.PostureDevice;
import com.aibaixun.system.domain.dto.BindDeviceDto;
import com.aibaixun.system.domain.dto.PostureDeviceDto;
import com.aibaixun.system.domain.dto.PostureDevicePageDto;
import com.aibaixun.system.domain.vo.ExportDeviceVo;
import com.aibaixun.system.domain.vo.PostureDeviceVo;
import com.aibaixun.system.domain.vo.QueryCabinetSpaceVo;
import com.aibaixun.system.domain.vo.QueryDeviceTreeVo;
import com.aibaixun.system.mapper.PostureDeviceMapper;
import com.aibaixun.system.service.DicmAddressService;
import com.aibaixun.system.service.DicmCabinetService;
import com.aibaixun.system.service.PostureDeviceService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 架式设备 服务层实现
 *
 * @author zhangyh
 */
@RequiredArgsConstructor
@Service
public class PostureDeviceServiceImpl extends ServiceImpl<PostureDeviceMapper, PostureDevice>
    implements PostureDeviceService {
    private static final Logger logger = LoggerFactory.getLogger(PostureDeviceServiceImpl.class);

    @Autowired
    private DicmCabinetService dicmCabinetService;

    @Override
    public R<Page<PostureDevice>> getPage(Page page, PostureDevicePageDto pageDto) {
        LambdaQueryWrapper<PostureDevice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(pageDto.getName()),PostureDevice::getName,pageDto.getName());
        queryWrapper.like(StringUtils.isNotBlank(pageDto.getCabinetNum()),PostureDevice::getCabinetNum,pageDto.getCabinetNum());
        queryWrapper.eq(pageDto.getLocation() != null,PostureDevice::getLocation,pageDto.getLocation());
        queryWrapper.eq(pageDto.getModel() != null,PostureDevice::getModel,pageDto.getModel());
        return R.ok(this.baseMapper.selectPage(page,queryWrapper));
    }

    @Override
    public R add(PostureDeviceDto dto) {
        DicmCabinet dicmCabinet = dicmCabinetService.getBaseMapper().selectOne(
            new LambdaQueryWrapper<DicmCabinet>()
            .eq(DicmCabinet::getAddressId,dto.getCabinetAddressId())
            .last("limit 1")
        );
        if(dicmCabinet == null){
            return R.fail("找不对对应的机柜信息！");
        }
        if(StringUtils.isBlank(dicmCabinet.getUeId())){
            return R.fail("机柜ueId不能为空，请先绑定！");
        }
        //校验当前位置是否有其他设备
        long count = this.baseMapper.checkPositionCount(dto);
        if(count > 0){
            return R.fail("当前位置已有其他设备，请先下架");
        }
        PostureDevice postureDevice = new PostureDevice();

        BeanCopyUtils.copy(dto,postureDevice);
        postureDevice.setCreateTime(LocalDateTime.now());
        //生成UE关联信息
        String ueRelation =  dicmCabinet.getUeId() + "_u_" + dto.getLocation();
        postureDevice.setUeRelation(ueRelation);
        postureDevice.setCabinetUeid(dicmCabinet.getUeId());
        this.baseMapper.insert(postureDevice);
        return R.ok();
    }

    @Override
    public R update(PostureDeviceDto dto) {
        PostureDevice postureDevice = this.baseMapper.selectById(dto.getDeviceId());
        if(postureDevice == null){
            return R.fail("设备信息不存在");
        }
        BeanCopyUtils.copy(dto,postureDevice);
        if((StringUtils.isNotBlank(dto.getCabinetAddressId()) && StringUtils.equals(dto.getCabinetAddressId(),postureDevice.getCabinetAddressId()))
            || (dto.getLocation() != null && dto.getLocation().intValue() != postureDevice.getLocation())){
            //改变了位置就需要进行验证
            long count = this.baseMapper.checkPositionCount(dto);
            if(count > 0){
                return R.fail("当前位置已有其他设备，请先下架");
            }
            DicmCabinet dicmCabinet = dicmCabinetService.getBaseMapper().selectOne(
                new LambdaQueryWrapper<DicmCabinet>()
                    .eq(DicmCabinet::getAddressId,dto.getCabinetAddressId())
                    .last("limit 1")
            );
            //生成UE关联信息
            String ueRelation =  dicmCabinet.getUeId() + "_u_" + dto.getLocation();
            postureDevice.setUeRelation(ueRelation);
            postureDevice.setCabinetUeid(dicmCabinet.getUeId());
        }
        this.baseMapper.updateById(postureDevice);
        return R.ok();
    }

    @Override
    public R delete(Long deviceId) {
        PostureDevice postureDevice = this.baseMapper.selectById(deviceId);
        if(postureDevice == null){
            return R.fail("设备信息不存在");
        }
        this.baseMapper.deleteById(deviceId);
        return R.ok();
    }

    @Override
    public R<List<PostureDeviceVo>> getList(PostureDeviceDto dto) {
//        LambdaQueryWrapper<PostureDevice> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.like(StringUtils.isNotBlank(dto.getName()),PostureDevice::getName,dto.getName());
//        queryWrapper.like(StringUtils.isNotBlank(dto.getCabinetNum()),PostureDevice::getCabinetNum,dto.getCabinetNum());
//        queryWrapper.eq(dto.getLocation() != null,PostureDevice::getLocation,dto.getLocation());
//        queryWrapper.eq(dto.getModel() != null,PostureDevice::getModel,dto.getModel());
        List<PostureDeviceVo> returnList = baseMapper.getDeviceList(dto);
//        return R.ok(this.baseMapper.selectList(queryWrapper));
        return R.ok(returnList);
    }

    @Override
    public R getCabinetSpace() {
        List<QueryCabinetSpaceVo> dataList = this.baseMapper.getCabinetSpace();
        if (CollectionUtil.isNotEmpty(dataList)){
            dataList.forEach(item -> {
                //计算空闲u位数
                Integer leisureUu = item.getUsum() - item.getUuse();
                item.setLeisureUu(leisureUu);
                //计算使用率
                BigDecimal bdNumerator = new BigDecimal(item.getUuse());
                BigDecimal bdDenominator = new BigDecimal(item.getUsum());
                BigDecimal result = bdNumerator.divide(bdDenominator, 2, RoundingMode.HALF_UP);
                item.setUtilizationRate(result.toString()+"%");
            });
        }
        return R.ok(dataList);
    }

    @Override
    public void addDevice(List<PostureDevice> saveList) {
        if (CollectionUtil.isNotEmpty(saveList)){
            saveList.forEach(item -> {
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("cabinet_num",item.getCabinetNum());
                queryWrapper.eq("name",item.getName());
                queryWrapper.eq("location",item.getLocation());
                PostureDevice postureDevice = baseMapper.selectOne(queryWrapper);
                if (null == postureDevice){
                    DicmAddress dicmAddress = baseMapper.queryDicmAddressByName(item.getCabinetNum());
                    if (null != dicmAddress) {
                        String ueId = dicmAddress.getUeId() + "_u_" + item.getLocation();
                        item.setUeRelation(ueId);
                        baseMapper.insert(item);
                    }
                }
            });
        }
    }

    @Override
    public List<PostureDevice> queryByRoomId(String cabinetId) {
        return baseMapper.queryByRoomId(cabinetId);
    }

    @Override
    public List<QueryDeviceTreeVo> queryDeviceList() {
        return baseMapper.queryDeviceList();
    }

    @Override
    public boolean checkDeviceUe(String ueId) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("ue_relation",ueId);
        PostureDevice postureDevice = baseMapper.selectOne(queryWrapper);
        if (null != postureDevice){
            return true;
        }
        return false;
    }

    @Override
    public boolean updateDeviceById(BindDeviceDto dto) {
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("device_id",dto.getId());
        updateWrapper.set("ue_relation",dto.getUeId());
        int update = baseMapper.update(null, updateWrapper);
        if (update != 0){
            return true;
        }
        return false;
    }

    @Override
    public R saveDeviceList(List<PostureDevice> postureDeviceList) {
        if(postureDeviceList.size() == 0){
            return R.fail("无数据");
        }
        List<PostureDevice> saveDeviceList = new ArrayList<>();
        Map<String, List<PostureDevice>> map = postureDeviceList.stream().collect(Collectors.groupingBy(PostureDevice::getCabinetUeid));
        for (String s : map.keySet()) {
            //查询机柜ueId
            DicmCabinet dicmCabinet = dicmCabinetService.getBaseMapper().selectOne(
                new LambdaQueryWrapper<DicmCabinet>()
                .eq(DicmCabinet::getUeId,s)
                .last("limit 1")
            );
            if(dicmCabinet == null){
                return R.fail("所属机柜UEID【"+s+"】不存在");
            }
            List<PostureDevice> deviceList = map.get(s);
            for (PostureDevice postureDevice : deviceList) {
                PostureDevice oldDevice = baseMapper.selectOne(
                    new LambdaQueryWrapper<PostureDevice>()
                    .eq(PostureDevice::getCabinetAddressId,postureDevice.getCabinetAddressId())
                    .eq(PostureDevice::getName,postureDevice.getName())
                    .last("limit 1")
                );
                String ueId = dicmCabinet.getUeId() + "_u_" + postureDevice.getLocation();
                if(oldDevice != null){
                    oldDevice.setUeRelation(ueId);
                    baseMapper.updateById(oldDevice);
                }else {
                    postureDevice.setUeRelation(ueId);
                    postureDevice.setCabinetAddressId(dicmCabinet.getAddressId());
                    postureDevice.setCabinetNum(dicmCabinet.getCabinetName());
                    postureDevice.setCreateTime(LocalDateTime.now());
                    postureDevice.setUpdateTime(LocalDateTime.now());
                    saveDeviceList.add(postureDevice);
                }
            }
        }
        if(saveDeviceList.size() > 0){
            this.saveBatch(saveDeviceList);
        }
        return R.ok();
    }

    @Override
    public List<ExportDeviceVo> exportDevice() {
        return baseMapper.queryDeviceAll();
    }

    @Override
    public List<PostureDevice> queryDeviceListByCabinet(List<String> addressNameList) {
        return baseMapper.queryDeviceListByCabinet(addressNameList);
    }

    @Override
    public void resetUeId() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("ue_relation","空");
        List<PostureDevice> postureDeviceList = baseMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(postureDeviceList)){
            postureDeviceList.forEach(item -> {
                item.setUeRelation("");
                baseMapper.updateById(item);
            });
        }
    }
}
